﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace LinqtoCRMApplication
{
    internal class XmlIndentingWriter : TextWriter 
    {
        private Regex indentingRegex = new Regex(@"\<\s*(?<tag>[\w\-]+)(\s+[\w\-]+\s*=\s*""[^""]*""|'[^']*')*\s*\>[^\<]*\<\s*/\s*\k<tag>\s*\>|\<[!\?]((?<=!)--((?!--\>).)*--\>|(""[^""]*""|'[^']'|[^>])*\>)|\<\s*(?<closing>/)?\s*[\w\-]+(\s+[\w\-]+\s*=\s*""[^""]*""|'[^']*')*\s*((/\s*)|(?<opening>))\>|[^\<]*", RegexOptions.ExplicitCapture | RegexOptions.Singleline| RegexOptions.Compiled);
        private TextWriter innerWriter;

        internal XmlIndentingWriter(TextWriter writer)
        {
            innerWriter = writer;
        }
        internal string IndentXml(string xml)
        {
            try
            {
                StringBuilder result = new StringBuilder(xml.Length * 2);
                int indent = 0;
                for (Match match = indentingRegex.Match(xml); match.Success; match = match.NextMatch())
                {
                    if (match.Groups["closing"].Success)
                        indent--;
                    result.AppendFormat("{0}{1}\r\n", new String(' ', indent * 2), match.Value);
                    if (match.Groups["opening"].Success && (!match.Groups["closing"].Success))
                        indent++;
                }
                return result.ToString();
            }
            catch
            {
                return xml;
            }
        }

        public override void WriteLine(string value)
        {
            innerWriter.WriteLine(IndentXml(value));
        }

        public override Encoding Encoding
        {
            get { return innerWriter.Encoding; }            
        }
    }
}
